package com.mac.nio.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

    /**
     * @Description
     * @auther machuan
     * @create 2020-04-17 15:21
     */
    public class SocketServer {
        public static void main(String[] args) throws Exception {
            //创建ServerSocketChannel，监听8080端口
            ServerSocketChannel ssc = ServerSocketChannel.open();
            //通过ServerSocket绑定8080端口
            ssc.socket().bind(new InetSocketAddress(8080));
            //设置非阻塞
            ssc.configureBlocking(false);
            //为ssc注册选择器
            Selector selector = Selector.open();
            ssc.register(selector, SelectionKey.OP_ACCEPT);
            //创建处理器
            Handler handler = new Handler(1024);
            while (true) {
                //等待请求，每次等待阻塞3s,超过3s后线程继续向下运行，如果传入0或者不传参则一直阻塞
                if (selector.select(3000) == 0) {
                    System.out.println("等待请求超时");
                    continue;
                }
                System.out.println("处理请求");
                //获取待处理的SelectionKey
                Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();

                while (keyIter.hasNext()) {
                    SelectionKey key = (SelectionKey) keyIter.next();
                    try {
                        //接收到连接请求时
                        if (key.isAcceptable()) {
                            handler.handleAccept(key);
                        }
                        //读数据
                        if (key.isReadable()) {
//                        handler.handleRead(key);
                            System.out.println("处理read请求");
                        }
                    } catch (IOException e) {
                        keyIter.remove();
                        continue;
                    }
                    //处理完后，从待处理的SelectionKey迭代器中移除当前所使用的key
                    keyIter.remove();
                }

            }

        }

        private static class Handler {
            private int bufferSize = 1024;
            private String localCharset = "UTF-8";

            public Handler() {

            }

            public Handler(int bufferSize) {
                this(bufferSize, null);
            }

            public Handler(String localCharset) {
                this(-1, localCharset);
            }

            public Handler(int bufferSize, String localCharset) {
                if (bufferSize > 0) {
                    this.bufferSize = bufferSize;
                }
                if (localCharset != null) {
                    this.localCharset = localCharset;
                }
            }

            public void handleAccept(SelectionKey key) throws IOException {
                //获取channel
                SocketChannel sc = (SocketChannel) key.channel();
                //获取buffer并重置
                ByteBuffer buffer = (ByteBuffer) key.attachment();
                buffer.clear();
                //没有读到内容则关闭
                if (sc.read(buffer) == -1) {
                    sc.close();
                } else {
                    //将buffer转换为在读状态
                    buffer.flip();
                    //将buffer中接收到的值按localCharset格式编码后保存到receivedString
                    String receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
                    System.out.println("接收到客户端：" + receivedString);
                    //返回数据给客户端
                    String sendString = "收到的数据：" + receivedString;
                    buffer = ByteBuffer.wrap(sendString.getBytes(localCharset));
                    sc.write(buffer);
                    sc.close();
                }

            }
        }
    }